package com.tjvib.view.activity;

import static com.tjvib.Constants.PARAM_ACCX;
import static com.tjvib.Constants.PARAM_ACCY;
import static com.tjvib.Constants.PARAM_ACCZ;
import static com.tjvib.Constants.PARAM_ALL;
import static com.tjvib.Constants.STANDARD_GB50010_STR;
import static com.tjvib.Constants.STANDARD_JGJ3_STR;
import static com.tjvib.Constants.STANDARD_JGJT411_2019;
import static com.tjvib.Constants.SUCCESS;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

import androidx.cardview.widget.CardView;

import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.LegendRenderer;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.DataPointInterface;
import com.jjoe64.graphview.series.LineGraphSeries;
import com.jjoe64.graphview.series.OnDataPointTapListener;
import com.jjoe64.graphview.series.PointsGraphSeries;
import com.jjoe64.graphview.series.Series;
import com.tjvib.Constants;
import com.tjvib.R;
import com.tjvib.base.BaseActivity;
import com.tjvib.util.LogUtil;
import com.tjvib.util.Manager.DataSetManager;
import com.tjvib.math.Complex;
import com.tjvib.math.FFT;
import com.tjvib.presenter.BasePresenter;
import com.tjvib.sensor.SensorData;
import com.tjvib.util.Manager.AppManager;
import com.tjvib.util.Manager.UserManager;
import com.tjvib.util.PoiUtil;
import com.tjvib.util.PressUtil;
import com.tjvib.util.ToastUtil;
import com.tjvib.util.retrofit.BaseResponse;
import com.tjvib.util.retrofit.RetrofitHelper;
import com.tjvib.view.dialog.LoadingDialog;
import com.tjvib.widget.AndroidScheduler;
import com.tjvib.widget.TitleLayout;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;

public class VsaActivity extends BaseActivity {

    private Button vsa_btn_confir, vsa_btn_export;
    private TextView vsa_tv_a, vsa_tv_std, vsa_tv_res;
    private EditText vsa_et_fre;
    private GraphView vsa_gv_data;
    private Spinner vsa_sp_sensor, vsa_sp_std, vsa_sp_scene;
    private RadioButton vsa_rb_all, vsa_rb_accx, vsa_rb_accy, vsa_rb_accz;
    private TitleLayout vsa_tit;

    private DataSetManager dataSetManager = DataSetManager.getInstance();
    private LineGraphSeries<DataPoint> mSeries1 = new LineGraphSeries<>(),
            mSeries2 = new LineGraphSeries<>(),
            mSeries3 = new LineGraphSeries<>();

    private String sensorSelect = "", curStandard, curScene;
    private double curAbsMax, a_std, f_std, maxAccX, maxAccY, maxAccZ,
            minAccX, minAccY, minAccZ, maxAbsAccX, maxAbsAccY, maxAbsAccZ;

    private ArrayList<String> scenesList = new ArrayList<>();
    private ArrayAdapter<String> scenesAdapter;
    private List<? extends SensorData> dataList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected int initLayout() {
        return R.layout.activity_vsa;
    }

    @Override
    protected boolean initView() {
        vsa_tit = findViewById(R.id.vsa_tit);
        vsa_tit.setTitle(getIntent().getStringExtra("METHOD"));

        vsa_btn_export = findViewById(R.id.vsa_btn_export);
        vsa_btn_export.setOnClickListener(v-> {
            FileReadWriteTask fileReadWriteTask = new FileReadWriteTask();
            fileReadWriteTask.execute();
        });

        vsa_gv_data = findViewById(R.id.vsa_gv_data);

        vsa_sp_sensor = findViewById(R.id.vsa_sp_sensor);
        vsa_sp_std = findViewById(R.id.vsa_sp_std);
        vsa_sp_scene = findViewById(R.id.vsa_sp_scene);

        vsa_rb_all = findViewById(R.id.vsa_rb_all);
        vsa_rb_accx = findViewById(R.id.vsa_rb_accx);
        vsa_rb_accy = findViewById(R.id.vsa_rb_accy);
        vsa_rb_accz = findViewById(R.id.vsa_rb_accz);
        vsa_rb_all.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b){
                onAxisChange(PARAM_ALL);
                if(maxAbsAccX > maxAbsAccY && maxAbsAccX > maxAbsAccZ){
                    curAbsMax = maxAbsAccX;
                    vsa_tv_a.setText("AccX=" + curAbsMax*9.8f);
                }else if(maxAbsAccY > maxAbsAccX && maxAbsAccY > maxAbsAccZ){
                    curAbsMax = maxAbsAccY;
                    vsa_tv_a.setText("AccY=" + curAbsMax*9.8f);
                }else if(maxAbsAccZ > maxAbsAccX && maxAbsAccZ > maxAbsAccY){
                    curAbsMax = maxAbsAccZ;
                    vsa_tv_a.setText("AccZ=" + curAbsMax*9.8f);
                }
            }
        });
        vsa_rb_accx.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b){
                onAxisChange(PARAM_ACCX);
                curAbsMax = maxAbsAccX;
                vsa_tv_a.setText("" + curAbsMax*9.8f);
            }
        });
        vsa_rb_accy.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b){
                onAxisChange(PARAM_ACCY);
                curAbsMax = maxAbsAccY;
                vsa_tv_a.setText("" + curAbsMax*9.8f);
            }
        });
        vsa_rb_accz.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b){
                onAxisChange(PARAM_ACCZ);
                curAbsMax = maxAbsAccZ;
                vsa_tv_a.setText("" + curAbsMax*9.8f);
            }
        });


        vsa_tv_std = findViewById(R.id.vsa_tv_std);
        vsa_tv_res = findViewById(R.id.vsa_tv_res);

        vsa_btn_confir = findViewById(R.id.vsa_btn_confir);
        vsa_btn_confir.setOnClickListener(v-> showResult());

        vsa_tv_a = findViewById(R.id.vsa_tv_a);
        vsa_et_fre = findViewById(R.id.vsa_et_fre);
        vsa_et_fre.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                if(vsa_et_fre.getText().length() > 0)
                    vsa_btn_confir.setBackground(getResources().getDrawable(R.drawable.selector_purple_rad40));
            }
        });

        return true;
    }

    @Override
    protected boolean initData() {
        List<String> sensorList = dataSetManager.getSensorList();
        SpinnerAdapter spinnerAdapter = new ArrayAdapter<>(this, R.layout.item_spinner_dropdown, sensorList);
        vsa_sp_sensor.setAdapter(spinnerAdapter);
        vsa_sp_sensor.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                vsa_rb_all.setChecked(true);
                sensorSelect = sensorList.get(position);
                drawGraph();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        ArrayList<String> standards = getStandards();
        ArrayAdapter<String> standardAdapter = new ArrayAdapter<>(this, R.layout.item_spinner_dropdown, standards);
        vsa_sp_std.setAdapter(standardAdapter);
        vsa_sp_std.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                curStandard = standards.get(position);
                changeScenes(curStandard);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                curStandard = standards.get(0);
                changeScenes(curStandard);
            }
        });

        scenesAdapter = new ArrayAdapter<>(this, R.layout.item_spinner_dropdown, scenesList);
        vsa_sp_scene.setAdapter(scenesAdapter);
        vsa_sp_scene.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                curScene = scenesList.get(position);
                showResult();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                curScene = scenesList.get(0);
                showResult();
            }
        });

        return true;
    }


    @Override
    protected BasePresenter genPresenter() {
        return null;
    }


    private void drawGraph() {
        if (sensorSelect.equals("local")) {
            dataList = dataSetManager.getDataSetContent(-1);
            maxAccX = dataSetManager.getAccMax(-1, 0);
            maxAccY = dataSetManager.getAccMax(-1, 1);
            maxAccZ = dataSetManager.getAccMax(-1, 2);
            minAccX = dataSetManager.getAccMin(-1, 0);
            minAccY = dataSetManager.getAccMin(-1, 1);
            minAccZ = dataSetManager.getAccMin(-1, 2);
        } else {
            dataList = dataSetManager.getDataSetContent(Integer.parseInt(sensorSelect));
            maxAccX = dataSetManager.getAccMax(Integer.parseInt(sensorSelect), 0);
            maxAccY = dataSetManager.getAccMax(Integer.parseInt(sensorSelect), 1);
            maxAccZ = dataSetManager.getAccMax(Integer.parseInt(sensorSelect), 2);
            minAccX = dataSetManager.getAccMin(Integer.parseInt(sensorSelect), 0);
            minAccY = dataSetManager.getAccMin(Integer.parseInt(sensorSelect), 1);
            minAccZ = dataSetManager.getAccMin(Integer.parseInt(sensorSelect), 2);
        }

        maxAbsAccX = Math.max(minAccX, maxAccX);
        maxAbsAccY = Math.max(minAccY, maxAccY);
        maxAbsAccZ = Math.max(minAccZ, maxAccZ);

        initGraphView();
        runOnUiThread(() -> {
            mSeries1.setThickness(3);
            mSeries2.setThickness(3);
            mSeries3.setThickness(3);
            mSeries1.setColor(Color.BLUE);
            mSeries2.setColor(Color.GREEN);
            mSeries3.setColor(Color.RED);
            vsa_gv_data.setBackgroundColor(Color.WHITE);
            mSeries1.setTitle("AccX");
            mSeries2.setTitle("AccY");
            mSeries3.setTitle("AccZ");
            vsa_gv_data.getLegendRenderer().setBackgroundColor(Color.TRANSPARENT);
            vsa_gv_data.getLegendRenderer().setVisible(true);
            vsa_gv_data.getLegendRenderer().setTextSize(18);
            vsa_gv_data.getLegendRenderer().setTextColor(R.color.main_grey_2);
            vsa_gv_data.getLegendRenderer().setAlign(LegendRenderer.LegendAlign.TOP);
            vsa_gv_data.getGridLabelRenderer().setHorizontalAxisTitle("时间(s)");
            vsa_gv_data.getGridLabelRenderer().setVerticalAxisTitle("幅值(g)");
            vsa_gv_data.getGridLabelRenderer().setHorizontalAxisTitleTextSize(24);
            vsa_gv_data.getGridLabelRenderer().setVerticalAxisTitleTextSize(24);
        });
    }


    private void initGraphView() {
        runOnUiThread(() -> {
            mSeries1.resetData(new DataPoint[]{});
            mSeries2.resetData(new DataPoint[]{});
            mSeries3.resetData(new DataPoint[]{});
            double miny = Double.MAX_VALUE, maxy = Double.MIN_VALUE;
            for (int m = 1; m < dataList.size(); m++) {
                SensorData data = dataList.get(m);
                float[] dataToShow = new float[3];
                int i = 0;
                while (i < 3) {
                    dataToShow[i] = data.acc[i];
                    maxy = Math.max(dataToShow[i], maxy);
                    miny = Math.min(dataToShow[i], miny);
                    i += 1;
                }

                mSeries1.appendData(new DataPoint(data.timestamp, dataToShow[0]), true, Integer.MAX_VALUE);
                mSeries2.appendData(new DataPoint(data.timestamp, dataToShow[1]), true, Integer.MAX_VALUE);
                mSeries3.appendData(new DataPoint(data.timestamp, dataToShow[2]), true, Integer.MAX_VALUE);
            }

            vsa_gv_data.getViewport().setScrollable(true);
            vsa_gv_data.getViewport().setScalable(true);
            if(dataList.size() != 0) {
                vsa_gv_data.getViewport().setMinX(0.0f);
                vsa_gv_data.getViewport().setMaxX(dataList.get(dataList.size() - 1).timestamp);
                vsa_gv_data.getViewport().setMaxY(maxy);
                vsa_gv_data.getViewport().setMinY(miny);
            }
        });
    }


    public ArrayList<String> getStandards() {
        ArrayList<String> dataList = new ArrayList<>();
        dataList.add(STANDARD_JGJ3_STR);
        dataList.add(STANDARD_GB50010_STR);
        dataList.add(STANDARD_JGJT411_2019);
        return dataList;
    }


    private void onAxisChange(int axis) {
        vsa_gv_data.removeAllSeries();
        switch (axis) {
            case PARAM_ACCX:
                vsa_gv_data.addSeries(mSeries1);
                break;
            case PARAM_ACCY:
                vsa_gv_data.addSeries(mSeries2);
                break;
            case PARAM_ACCZ:
                vsa_gv_data.addSeries(mSeries3);
                break;
            case PARAM_ALL:
                vsa_gv_data.addSeries(mSeries1);
                vsa_gv_data.addSeries(mSeries2);
                vsa_gv_data.addSeries(mSeries3);
            default:
                break;
        }
    }


    private void showResult() {
        if(vsa_et_fre.getText().toString().trim().isEmpty()){
            ToastUtil.show("请输入自振频率");
            return;
        }
        double fre = Double.parseDouble(vsa_et_fre.getText().toString().trim());
        switch (curStandard) {
            case STANDARD_JGJ3_STR:
                switch (curScene) {
                    case "住宅、办公":
                        if (fre <= 2) {
                            a_std = 0.07;
                        } else if (fre >= 4) {
                            a_std = 0.05;
                        } else {
                            a_std = (4 - fre) / 100 + 0.05;
                        }
                        break;
                    case "商场、室内连廊":
                        if (fre <= 2) {
                            a_std = 0.22;
                        } else if (fre >= 4) {
                            a_std = 0.15;
                        } else {
                            a_std = 0.035 * (4 - fre) + 0.15;
                        }
                        break;
                }
                showJGJ3Result();
                break;
            case STANDARD_GB50010_STR:
                switch (curScene) {
                    case "住宅和公寓":
                        f_std = 5;
                        break;
                    case "办公楼和旅馆":
                        f_std = 4;
                        break;
                    case "大跨公共建筑":
                        f_std = 3;
                        break;
                }
                showGB50010Result(fre);
                break;
            case STANDARD_JGJT411_2019:
                switch (curScene) {
                    case "手术室":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.025;
                        break;
                    case "住宅、病房、办公室、教室、宿舍、旅馆、幼儿园":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.05;
                        break;
                    case "商场、餐厅、公共交通等候大厅、剧场、礼堂":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.15;
                        break;
                    case "舞厅、演出舞台、看台、室内运动场地":
                        if(fre < 4){
                            ToastUtil.show("自振频率f不应小于4Hz");
                            return;
                        }
                        a_std = 0.5;
                        break;
                    case "同时进行有氧健身操和器械健身的健身房":
                        if(fre < 4){
                            ToastUtil.show("自振频率f不应小于4Hz");
                            return;
                        }
                        a_std = 0.2;
                        break;
                    case "车间办公室":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.2;
                        break;
                    case "安装娱乐振动设备":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.35;
                        break;
                    case "生产操作区":
                        if(fre < 3){
                            ToastUtil.show("自振频率f不应小于3Hz");
                            return;
                        }
                        a_std = 0.4;
                        break;
                    case "封闭连廊和室内天桥":
                        if(fre < 1.2){
                            ToastUtil.show("自振频率f不应小于1.2Hz");
                            return;
                        }
                        a_std = 0.15;
                        break;
                    case "不封闭连廊":
                        if(fre < 1.2){
                            ToastUtil.show("自振频率f不应小于1.2Hz");
                            return;
                        }
                        a_std = 0.5;
                        break;
                }
                showJGJTResult();
                break;
        }
    }


    public void changeScenes(String standard) {
        switch (standard) {
            case STANDARD_JGJ3_STR:
                scenesList.clear();
                scenesList.add("住宅、办公");
                scenesList.add("商场、室内连廊");
                scenesAdapter.notifyDataSetChanged();
                vsa_sp_scene.setSelection(0);
                curScene = scenesList.get(0);
                break;
            case STANDARD_GB50010_STR:
                scenesList.clear();
                scenesList.add("住宅和公寓");
                scenesList.add("办公楼和旅馆");
                scenesList.add("大跨公共建筑");
                scenesAdapter.notifyDataSetChanged();
                vsa_sp_scene.setSelection(0);
                curScene = scenesList.get(0);
                break;
            case STANDARD_JGJT411_2019:
                scenesList.clear();
                scenesList.add("手术室");
                scenesList.add("住宅、病房、办公室、教室、宿舍、旅馆、幼儿园");
                scenesList.add("商场、餐厅、公共交通等候大厅、剧场、礼堂");
                scenesList.add("舞厅、演出舞台、看台、室内运动场地");
                scenesList.add("同时进行有氧健身操和器械健身的健身房");
                scenesList.add("车间办公室");
                scenesList.add("安装娱乐振动设备");
                scenesList.add("生产操作区");
                scenesList.add("封闭连廊和室内天桥");
                scenesList.add("不封闭连廊");
                scenesAdapter.notifyDataSetChanged();
                vsa_sp_scene.setSelection(0);
                curScene = scenesList.get(0);
                break;
        }
    }


    public void showJGJ3Result() {
        vsa_tv_std.setText("a <= " + String.format("%.6f m/s²", a_std));
        if (curAbsMax*9.8f <= a_std) {
            vsa_tv_res.setText("结果达标");
        } else {
            vsa_tv_res.setText("结果不达标");
        }
    }


    private void showGB50010Result(double fre) {
        vsa_tv_std.setText("f >= " + String.format("%.6f Hz", f_std));
        if (fre >= f_std) {
            vsa_tv_res.setText("结果达标");
        } else {
            vsa_tv_res.setText("结果不达标");
        }
    }


    private void showJGJTResult() {
        vsa_tv_std.setText("a <= " + String.format("%.6f m/s²", a_std));
        if (curAbsMax*9.8f <= a_std) {
            vsa_tv_res.setText("结果达标");
        } else {
            vsa_tv_res.setText("结果不达标");
        }
    }


    private class FileReadWriteTask extends AsyncTask<Void, Void, Void> {
        private LoadingDialog loadingDialog = null;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            loadingDialog = new LoadingDialog(VsaActivity.this);
            loadingDialog.showDialog(VsaActivity.this, "正在输出报告...", 5);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            SimpleDateFormat sdf = new SimpleDateFormat();
            sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
            Date date = new Date();

            Map<String, String> replacements = new HashMap<>();
            replacements.put("【时间】", sdf.format(date));
            replacements.put("【姓名】", UserManager.getInstance().getUsername());
            replacements.put("【传感器】", vsa_sp_sensor.getSelectedItem().toString().trim());
            replacements.put("【标准选择】", vsa_sp_std.getSelectedItem().toString().trim());
            replacements.put("【场景选择】", vsa_sp_scene.getSelectedItem().toString().trim());
            replacements.put("【加速度】", vsa_tv_a.getText().toString().trim());
            replacements.put("【自振频率】", vsa_et_fre.getText().toString().trim());
            replacements.put("【规范】", vsa_tv_std.getText().toString().trim());
            replacements.put("【结果】", vsa_tv_res.getText().toString().trim());
            Bitmap bitmap = PoiUtil.loadBitmapFromView(vsa_gv_data);

            synchronized (PoiUtil.class) {
                PoiUtil.replaceFieldsWithImage(bitmap, VsaActivity.this, Constants.METHOD_VSA,
                        sdf.format(date) + ".docx", replacements);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void unused) {
            super.onPostExecute(unused);
            if(loadingDialog != null) loadingDialog.dismiss();
            ToastUtil.show("报告已保存");
        }
    }
}